/*
Copyright (C) 2011  Christoph Schnack, Berlin (Germany)

This file is part of Tribuit.

    Tribuit is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Tribuit is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Tribuit.  If not, see <http://www.gnu.org/licenses/>.
*/
package Wordcheck;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import GuiTools.*;
import Settings.*;
import Storage.*;

/**
 * @author Christoph Schnack
 *
 */
class InterrogationPanel extends JPanel{
	private Font valFont = new Font(Font.SANS_SERIF,Font.BOLD,12),keyFont = new Font(Font.SANS_SERIF,Font.PLAIN,12),meaningFont = new Font(Font.SANS_SERIF,Font.BOLD,25), phoneticFont = new Font(Font.SERIF,Font.BOLD,15);
	private JComponent focusComponent;
	private Settings SET;
	private Language LANG;
	private Wordcheck WCK;
	private Word word;
	private JLabel tcLabel;
	private TermClass termClassA,termClassB;
	private DisplayPanel displayPanel;
	private InputPanel inputPanel;
	private ActionListener testListener;
	private StringBuffer wrongAnswerSB;
	private String errorMessage;
	
	public InterrogationPanel(Settings set,Wordcheck wck,Word w,TermClass tcA, Vector<String> categoriesA, TermClass tcB, Vector<String> categoriesB, ActionListener al, ActionListener solveListener){
		super();
		SET = set;
		LANG = set.getLanguage();
		WCK = wck;
		word = w;
		termClassA = tcA;
		termClassB = tcB;
		testListener = al;
		
		tcLabel = new JLabel();
		tcLabel.setFont(new Font(Font.SERIF,Font.PLAIN,14));
		JPanel tcPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		tcPanel.add(tcLabel);
		
		displayPanel = (WCK.getTestLang2())?new DisplayPanel(word.getMeaningVectorB(),termClassB,word.getTermclassB(),word.getLection()):new DisplayPanel(word.getMeaningVectorA(),termClassA,word.getTermclassA(),word.getLection());		
		inputPanel = (WCK.getTestLang2())? new InputPanel(word.getMeaningVectorA(),termClassA,categoriesA):new InputPanel(word.getMeaningVectorB(),termClassB,categoriesB);
		
		JLabel promptLabel = new JLabel(WCK.getTestLang2Name()+":");
		promptLabel.setFont(new Font(Font.SANS_SERIF,Font.ITALIC,12));
		promptLabel.setAlignmentY(JLabel.LEFT_ALIGNMENT);
		JPanel promptPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		promptPanel.add(promptLabel);
		
		//enter/solve buttons
		JButton enterBtn = new JButton("enter");
		enterBtn.addActionListener(testListener);
		enterBtn.setMnemonic(KeyEvent.VK_ENTER);
		enterBtn.setToolTipText("ALT + ENTER");
		JButton nextBtn = new JButton(WCK.TESTMODUS?LANG.getNext():LANG.getSolve());
		nextBtn.addActionListener(solveListener);
		nextBtn.setMnemonic(KeyEvent.VK_L);
		nextBtn.setToolTipText(LANG.getAltL());
		JPanel buttonPanel = new JPanel();
		buttonPanel.add(enterBtn);
		buttonPanel.add(nextBtn);
	
		this.setLayout(new GridBagLayout());
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.insets = new Insets(0,0,0,0);
		gbc.anchor = GridBagConstraints.NORTH;
		gbc.fill = GridBagConstraints.NONE;
		gbc.anchor = GridBagConstraints.NORTHWEST;
		gbc.gridx = 0;
		gbc.gridy = 0;
		this.add(tcPanel,gbc);
		gbc.anchor = GridBagConstraints.NORTH;
		gbc.gridy++;
		this.add(displayPanel,gbc);
		gbc.anchor = GridBagConstraints.NORTHWEST;
		gbc.gridy++;
		gbc.insets = new Insets(5,0,0,0);
		this.add(promptPanel, gbc);
		gbc.fill = GridBagConstraints.BOTH;
		gbc.anchor = GridBagConstraints.NORTHWEST;
		gbc.gridy++;
		gbc.insets = new Insets(5,0,0,0);
		this.add(inputPanel,gbc);
		gbc.gridy++;
		gbc.insets = new Insets(10,10,10,10);
		this.add(buttonPanel,gbc);
	}
	
	public void setWord(Word wrd,TermClass tcA, Vector<String> categoriesA, TermClass tcB, Vector<String> categoriesB){
		word = wrd;
		termClassA = tcA;
		termClassB = tcB;
		if(WCK.getTestLang2()){
			displayPanel.setUpMeanings(word.getMeaningVectorB(),termClassB, word.getTermclassB(),word.getLection());
			inputPanel.setUpMeanings(word.getMeaningVectorA(),termClassA,categoriesA);
		}
		else{
			displayPanel.setUpMeanings(word.getMeaningVectorA(),termClassA, word.getTermclassA(),word.getLection());
			inputPanel.setUpMeanings(word.getMeaningVectorB(),termClassB,categoriesB);
		}
	}
	
	public void focusFirstComponent(){
		inputPanel.focusFirstComponent();
	}
	
	private class InputPanel extends JPanel{
		private Vector<MeaningInputPanel> meanings = new Vector<MeaningInputPanel>();
		private TermClass termClass;
		public InputPanel(Vector<Meaning> mngs, TermClass tc, Vector<String> cats){
			super();
			this.setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
			setUpMeanings(mngs,tc,cats);
		}
		
		public void setUpMeanings(Vector<Meaning> mngs, TermClass tc, Vector<String> cats){
			termClass = tc;
			meanings.clear();
			this.removeAll();
			int counter = 1;
			for(Meaning m : mngs){
				meanings.add(new MeaningInputPanel(m, tc, cats,""+counter++));
				this.add(meanings.lastElement());
			}
		}
		
		public void focusFirstComponent(){
			if(termClass!=null && meanings.size()>0){
				if(!termClass.hasPrefix() || (termClass.getPreFixVal()!=null && termClass.getPreFixVal().size()==1)){
					meanings.firstElement().focusTF();
				}
				else meanings.firstElement().focusArticle();
			}
		}
		
		public boolean checkInputs(){
			boolean allCorrect = true;
			for(MeaningInputPanel mip : meanings){
				if(!mip.checkInputs()) allCorrect = false;
			}
			return allCorrect;
		}
	}
	
	private class MeaningInputPanel extends JPanel{
		private HashMap<String,MetaElement> metaElements = new HashMap<String,MetaElement>();
		private Vector<TermPanel> synonymTPs = new Vector<TermPanel>();
		private TermPanel termPanel;
		private JPanel metaPanel,synonymsPanel,categoryPanel;
		private Meaning meaning;
		private TermClass termClass;
		private String index;
		
		public MeaningInputPanel(Meaning mng, TermClass tc, Vector<String> cats, String ind){
			super();
			index = ind;
			termPanel = new TermPanel(SET, tc, cats, index);
			termPanel.setTFActionListener(testListener);
			synonymsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
			metaPanel = new JPanel();
			categoryPanel = new JPanel();
			JPanel chiefPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
			chiefPanel.add(termPanel);
			chiefPanel.add(metaPanel);
			chiefPanel.add(categoryPanel);
			this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
			this.add(chiefPanel);
			this.add(synonymsPanel);
			setMeaning(mng,tc,cats);
		}
		
		public void setMeaning(Meaning m, TermClass tc, Vector<String> cats){
			meaning = m;
			termClass = tc;
			termPanel.resetAllData();
			termPanel.setTermClass(tc);
			termPanel.removeCategoryLP();
			termPanel.setCategory(m.getCategory());
			synonymTPs.clear();
			categoryPanel.removeAll();
			JLabel categoryLabel = new JLabel((m.hasCategory()?"("+m.getCategory()+")":""));
			categoryLabel.setFont(new Font(Font.SANS_SERIF,Font.ITALIC,14));
			categoryPanel.add(categoryLabel);
			synonymsPanel.removeAll();
			if(m.hasSynonyms()&&WCK.getTestSynonyms()){
				int ind =1;
				for(Term synonym : m.getSynonyms()){
					synonymTPs.add(new TermPanel(SET,tc,cats,LANG.getSynonym()+" "+ind++));
					synonymsPanel.add(synonymTPs.lastElement());
					synonymTPs.lastElement().setTFActionListener(testListener);
				}
			}
			metaPanel.removeAll();
			metaElements.clear();
			if(m.hasMeta()&&WCK.getTestMetas()){
				for(String key : tc.getSortedKeys()){
					if(meaning.hasMetaEntryFor(key)){
						metaElements.put(key, new MetaElement(SET,key, tc.getValues(key), testListener));
						metaPanel.add(metaElements.get(key));
					}
				}
			}
		}
		
		public boolean checkInputs(){
			boolean allCorrect = true;
			wrongAnswerSB.append(LANG.getMeaning().toUpperCase()+" "+index+": <BLOCKQUOTE>");
			ComparisonResult result = compareTerm(meaning.getMeaningAsTerm(),termPanel);
			if(!result.getAllCorrect()){
				allCorrect = false;
				focusComponent = result.getFocusComponent();
				errorMessage = result.getErrorMessage();
			}
			if(WCK.getTestMetas() && !termClass.isEmpty() && meaning.hasMeta()){
				wrongAnswerSB.append(LANG.getMetainformation().toUpperCase()+": <br><BLOCKQUOTE>");
				for(String key : metaElements.keySet().toArray(new String[]{})){
					wrongAnswerSB.append(key+": "+(metaElements.get(key).getValue().equals("")?"- ":metaElements.get(key).getValue())+"<br>");
					if( !metaElements.get(key).getValue().toLowerCase().equals(meaning.getMetaElement(key).toLowerCase()) ){
						if(allCorrect){
							allCorrect = false;
							focusComponent = metaElements.get(key).getInputComponent();
							errorMessage = LANG.getMetainformation()+ " " + key + " "+LANG.getIsWrong();
						}
					}
				}
				wrongAnswerSB.append("</BLOCKQUOTE> ");
			}
			if(WCK.getTestSynonyms() && meaning.hasSynonyms()){
				int i = 0;
				wrongAnswerSB.append("SYNONYMS:<BLOCKQUOTE> ");
				for(Term term : meaning.getSynonyms()){
					result = compareTerm(term,synonymTPs.elementAt(i++));
					if(!result.getAllCorrect()){
						if(allCorrect){
							allCorrect = false;
							focusComponent = result.getFocusComponent();
							errorMessage = result.getErrorMessage();
						}
					}
				}
				wrongAnswerSB.append("</BLOCKQUOTE> ");
			}
			wrongAnswerSB.append("</BLOCKQUOTE></BODY></HTML>");
			return allCorrect;
		}
		
		public ComparisonResult compareTerm(Term meaning,TermPanel termPanelArg){
			boolean allCorrect = true;
			JComponent focusComponent = null;
			String errorMessage = "";
			if(termClass.hasPrefix()){
				if(meaning.hasArticle()) wrongAnswerSB.append(getMeaningArticle().equals("")?"(-) ":getMeaningArticle()+" ");
				if((!meaning.hasArticle() && termPanelArg.getArticle().equals("")) || !meaning.getArticle().toLowerCase().equals(termPanelArg.getArticle().toLowerCase())){
					if(allCorrect){
						allCorrect = false;
						focusComponent = termPanelArg.getArticleComponent();
						errorMessage = termClass.getPreFixName()+ " " + index + " " + LANG.getIsWrong();
					}
				}
			}
			wrongAnswerSB.append(termPanelArg.getMeaning().equals("")?"- ":termPanelArg.getMeaning()+" ");
			if(termPanelArg.getMeaning().equals("") || (!meaning.getTerm().toLowerCase().trim().equals(termPanelArg.getMeaning().toLowerCase()))){
				if(allCorrect){
					allCorrect = false;
					focusComponent = termPanelArg.getMeaningTF();
					errorMessage = LANG.getMeaning()+ " " + termPanelArg.getLabelTitle()+" " + LANG.getIsWrong(); 
				}
			}
			wrongAnswerSB.append("["+getMeaningCategory()+"] ");
			if(!meaning.getCategory().equals(getMeaningCategory())){
				if(allCorrect){
					allCorrect = false;
					focusComponent = termPanelArg.getCategoryComponent();
					errorMessage = LANG.getCategory()+ " " + index + " " + LANG.getIsWrong();
				}
			}
			wrongAnswerSB.append("<br>");
			return new ComparisonResult(allCorrect,errorMessage,focusComponent);
		}
		
		public void focusTF(){
			termPanel.grabFocusMeaningTF();
		}
		
		public void focusArticle(){
			termPanel.grabFocusArticle();
		}
		
		public TribuitTextField getMeaningTF(){
			return termPanel.getMeaningTF();
		}
		
		public String getMeaningInput(){
			return termPanel.getMeaning().trim();
		}
		
		public String getMeaningArticle(){
			return termPanel.getArticle().trim();
		}
		
		public String getMeaningCategory(){
			return termPanel.getCategory().trim();
		}
	}
	
	private class ComparisonResult{
		private String errorMessage;
		private JComponent focusComponent;
		private boolean allCorrect;
		
		public ComparisonResult(boolean ac, String em, JComponent fc){
			errorMessage = em;
			focusComponent = fc;
			allCorrect = ac;
		}
		
		public String getErrorMessage(){ return allCorrect?"":errorMessage;}
		public boolean getAllCorrect(){ return allCorrect;}
		public JComponent getFocusComponent(){ return focusComponent;}
	}
	
	private class DisplayPanel extends JPanel{
		private TermClass termClass;
		private JPanel meaningsPanel;
		private GridBagConstraints gbc,wlgbc, mgbc;
		private int rowCounter = 0;
		private Insets noInsets = new Insets(0,0,0,0),meaningInsets=new Insets(5,20,0,20),spaceLeftFiveInsets=new Insets(0,5,0,0),spaceLeftTenInsets=new Insets(0,10,0,0);
		
		public DisplayPanel(Vector<Meaning> mngs, TermClass tc, String tcName, String section){
			super();
			termClass = tc;
			meaningsPanel = new JPanel();
			meaningsPanel.setLayout(new GridBagLayout());
			gbc = new GridBagConstraints();
			wlgbc = new GridBagConstraints();
			wlgbc.fill = GridBagConstraints.BOTH;
			wlgbc.anchor = GridBagConstraints.WEST;
			wlgbc.weightx = 1;
			mgbc = new GridBagConstraints();
			mgbc.anchor = GridBagConstraints.NORTHWEST;
			mgbc.fill = GridBagConstraints.BOTH;
			mgbc.weightx = 1;

			setUpMeanings(mngs,tc,tcName,section);
			this.setLayout(new BorderLayout());
			this.add(BorderLayout.CENTER,meaningsPanel);
		}

		public void setUpMeanings(Vector<Meaning> mngs, TermClass tc, String tcName, String section){
			termClass = tc;
			meaningsPanel.removeAll();
			tcLabel.setText(tcName+", "+section);
			rowCounter = 0;
			gbc.gridy = 0;
			gbc.gridx = 0;
			gbc.fill = GridBagConstraints.BOTH;
			gbc.anchor = GridBagConstraints.NORTHWEST;
			gbc.weighty = 1;
			gbc.weightx = 1;
			for(Meaning m : mngs){
				gbc.weightx = 0;
				JLabel wordLabel = new JLabel(((mngs.size()>1)?(rowCounter+1)+".: ":"")+m.getMeaningWithArticle());
				wordLabel.setFont(meaningFont);
				JPanel wordPanel = new JPanel();
				wordPanel.setLayout(new GridBagLayout());
				wlgbc.gridy = 0;
				wordPanel.add(wordLabel,wlgbc);
				if(m.hasSynonyms()){
					JLabel synonymsLabel = new JLabel(m.getSynonymsAsString());
					wlgbc.gridy = 1;
					wordPanel.add(synonymsLabel,wlgbc);
				}
				
				JPanel infoPanel = new JPanel();
				infoPanel.setLayout(new GridBagLayout());
				if(m.hasCategory()){
					JLabel catLabel = new JLabel(LANG.getCategory()+": "+m.getCategory());
					catLabel.setVerticalAlignment(SwingConstants.TOP);
					infoPanel.add(catLabel,gbc);
					++gbc.gridy;
				}
				if(m.hasPhonetic()){
					JLabel phoneticLabel = new JLabel(m.getPhonetic());
					phoneticLabel.setFont(phoneticFont);
					phoneticLabel.setVerticalAlignment(SwingConstants.TOP);
					infoPanel.add(phoneticLabel,gbc);
					++gbc.gridy;
				}
				if(m.hasMeta()){
					JPanel metaPanel = new JPanel();
					metaPanel.setLayout(new GridBagLayout());
					mgbc.gridy =0;
					mgbc.gridwidth =1;
					for(String key : termClass.getSortedKeys()){
						if(m.hasMetaEntryFor(key)){
							mgbc.gridy++;
							JLabel keyLabel = new JLabel(key+":");
							keyLabel.setHorizontalAlignment(SwingConstants.LEFT);
							keyLabel.setFont(keyFont);
							JLabel valLabel = new JLabel(m.getMetaElement(key));
							valLabel.setFont(valFont);
							mgbc.gridx = 1;
							mgbc.insets = noInsets;
							metaPanel.add(keyLabel,mgbc);
							mgbc.gridx = 2;
							mgbc.insets = spaceLeftTenInsets;
							metaPanel.add(valLabel,mgbc);
						}
					}
					mgbc.weighty =1;
					++mgbc.gridy;
					mgbc.gridwidth =2;
					metaPanel.add(new JPanel(),mgbc);
					infoPanel.add(metaPanel,gbc);
				}
				if(m.hasNote()){
					CustomTextArea noteTA = new CustomTextArea(m.getNote(), false, false);
					JScrollPane noteSP = new JScrollPane(noteTA);
					noteSP.setPreferredSize(new Dimension(130,60));
					LabelPanel noteLP = new LabelPanel(LANG.getNote()+":",noteSP);
					noteLP.setOpaque(false);
					gbc.gridy = 0;
					++gbc.gridx;
					gbc.gridheight = 100;
					gbc.insets = spaceLeftFiveInsets;
					infoPanel.add(noteLP,gbc);
				}
				if(m.hasExampleSentence()){
					CustomTextArea esTA = new CustomTextArea(m.getExampleSentence(), false, false);
					CustomScrollPane jsp = new CustomScrollPane(esTA);
					jsp.setPreferredSize(new Dimension(130,60));
					LabelPanel lp = new LabelPanel(LANG.getExampleSentence()+":",jsp);
					lp.setOpaque(false);
					gbc.gridy = 0;
					gbc.gridheight = 100;
					++gbc.gridx;
					gbc.insets = spaceLeftFiveInsets;
					infoPanel.add(lp,gbc);
				}
				gbc.gridheight = 1;
				gbc.weightx = 1;
				++gbc.gridx;
				infoPanel.add(new JPanel(),gbc);
				gbc.gridx = 0;
				gbc.gridy = rowCounter;
				gbc.anchor = GridBagConstraints.NORTHWEST;
				gbc.insets = meaningInsets;
				meaningsPanel.add(wordPanel,gbc);
				gbc.gridx = 1;
				gbc.weightx = 0;
				gbc.insets = noInsets;
				meaningsPanel.add(infoPanel,gbc);
				++rowCounter;
			}
		}
	}
	
	public boolean checkInputs(){
		errorMessage = null;
		wrongAnswerSB = new StringBuffer();
		wrongAnswerSB.append("<HTML><BODY>");
		return inputPanel.checkInputs();
	}
	
	public String getErrorMessage(){
		return errorMessage;
	}
	
	public String getWrongAnswerString(){
		return wrongAnswerSB.toString();
	}
	
	public void grabFocusFaultyComponent(){
		if(focusComponent!=null){
			if(focusComponent.getClass().getName().equals("GuiTools.TribuitTextField")){
				TribuitTextField tf = (TribuitTextField) focusComponent;
				tf.selectAll();
			}
			focusComponent.grabFocus();
		}
	}
	
}
